package com.xxl.job.admin.controller.interceptor;

import com.alibaba.fastjson.JSON;
import com.baomidou.kisso.SSOHelper;
import com.baomidou.kisso.common.SSOConstants;
import com.baomidou.kisso.security.token.SSOToken;
import com.baomidou.kisso.web.handler.KissoDefaultHandler;
import com.baomidou.kisso.web.handler.SSOHandlerInterceptor;
import com.tas.core.base.utils.BaseFieldConstants;
import com.tas.core.base.utils.LogUtils;
import com.tas.core.base.vo.SecurityVo;
import com.xxl.job.admin.controller.annotation.PermessionLimit;
import com.xxl.job.admin.core.conf.XxlJobAdminConfig;
import com.xxl.job.admin.core.util.CookieUtil;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.util.DigestUtils;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.lang.reflect.Method;
import java.math.BigInteger;


/**
 * @Author kevin
 * @Date 2018/12/20 18:30
 * @Description
 */
@Component
public class AccessInterceptor extends HandlerInterceptorAdapter {

    private static final Logger logger = LoggerFactory.getLogger(AccessInterceptor.class);
    private SSOHandlerInterceptor handlerInterceptor;



    @Value("${kisso.config.cookieName:__sid}")
    private String sidName;
    @Resource
    private WhiteDomainConfig domainConfig;

    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
            throws Exception {
        setAllowOrigin(request, response);
        if (handler instanceof HandlerMethod) {
            HandlerMethod handlerMethod = (HandlerMethod) handler;
            Method method = handlerMethod.getMethod();
            if ("errorHtml".equals(method.getName())) {
                return true;
            }
            SSOToken ssoToken = null;
            try{
                ssoToken =  SSOHelper.getSSOToken(request);
            }catch (Exception e){

            }

            if (null == ssoToken && isMiniAppRequest(request)) {
                if (logger.isDebugEnabled()) {
                    logger.debug("权限拦截处理，cookie里无权限数据的时候从参数里再处理权限。");
                }
            }

            if (null == ssoToken) {
                if (!ifLogin(request)) {
                    PermessionLimit permission = handlerMethod.getMethodAnnotation(PermessionLimit.class);
                    if (permission == null || permission.limit()) {
                        if (logger.isDebugEnabled()) {
                            LogUtils.debug(logger, "权限拦截获取token为空，需要登录。");
                        }
                        response.sendRedirect("/");
                        return false;
                    }
                }
            } else {
                request.setAttribute(SSOConstants.SSO_TOKEN_ATTR, ssoToken);
                Long userId = Long.valueOf(ssoToken.getId());
                SecurityVo securityVo = new SecurityVo(userId);
                request.setAttribute(BaseFieldConstants.AUTH_HEADER, JSON.toJSONString(securityVo));
            }
            if (logger.isDebugEnabled()) {
                LogUtils.debug(logger, "权限拦截处理结束...");
            }

        }

        /**
         * 通过拦截
         */
        return true;
    }


    public static final String LOGIN_IDENTITY_KEY = "XXL_JOB_LOGIN_IDENTITY";
    private static String LOGIN_IDENTITY_TOKEN;
    public static String getLoginIdentityToken() {
        if (LOGIN_IDENTITY_TOKEN == null) {
            String username = XxlJobAdminConfig.getAdminConfig().getLoginUsername();
            String password = XxlJobAdminConfig.getAdminConfig().getLoginPassword();

            // login token
            String tokenTmp = DigestUtils.md5DigestAsHex(String.valueOf(username + "_" + password).getBytes());		//.getBytes("UTF-8")
            tokenTmp = new BigInteger(1, tokenTmp.getBytes()).toString(16);

            LOGIN_IDENTITY_TOKEN = tokenTmp;
        }
        return LOGIN_IDENTITY_TOKEN;
    }

    public static boolean login(HttpServletResponse response, String username, String password, boolean ifRemember){

        // login token
        String tokenTmp = DigestUtils.md5DigestAsHex(String.valueOf(username + "_" + password).getBytes());
        tokenTmp = new BigInteger(1, tokenTmp.getBytes()).toString(16);

        if (!getLoginIdentityToken().equals(tokenTmp)){
            return false;
        }

        // do login
        CookieUtil.set(response, LOGIN_IDENTITY_KEY, getLoginIdentityToken(), ifRemember);
        return true;
    }
    public static void logout(HttpServletRequest request, HttpServletResponse response){
        CookieUtil.remove(request, response, LOGIN_IDENTITY_KEY);
    }
    public static boolean ifLogin(HttpServletRequest request){
        String indentityInfo = CookieUtil.getValue(request, LOGIN_IDENTITY_KEY);
        if (indentityInfo==null || !getLoginIdentityToken().equals(indentityInfo.trim())) {
            return false;
        }
        return true;
    }




    private boolean isMiniAppRequest(HttpServletRequest request){
        //ios 下有问题，先返回true TODO
        return true;
    }
    private void setAllowOrigin(HttpServletRequest request, HttpServletResponse response) {
        String origin = request.getHeader("Origin");
        if(StringUtils.isNotEmpty(origin)){
            String domain = origin.substring(origin.indexOf("//") + 2);
            int portIndex = domain.indexOf(":");
            if(portIndex > 0){
                domain = domain.substring(0, portIndex);
            }

            if(domainConfig.hasAuth(domain)){
                response.setHeader("Access-Control-Allow-Origin", origin);
                response.setHeader("Access-Control-Allow-Credentials","true");
                response.setHeader("Access-Control-Allow-Headers","Origin, X-Requested-With, Content-Type, Accept");
                response.setHeader("Access-Control-Allow-Methods", "GET, POST");
            }
        }
    }


    public SSOHandlerInterceptor getHandlerInterceptor() {
        if (handlerInterceptor == null) {
            return KissoDefaultHandler.getInstance();
        }
        return handlerInterceptor;
    }

    public void setHandlerInterceptor(SSOHandlerInterceptor handlerInterceptor) {
        this.handlerInterceptor = handlerInterceptor;
    }

}
